use crate::pkg::token;
use actix_web::{
    dev::{forward_ready, Service, ServiceRequest, ServiceResponse, Transform},
    error, Error,
};
use futures_util::future::LocalBoxFuture;
use std::future::{ready, Ready};

// There are two steps in middleware processing.
// 1. Middleware initialization, middleware factory gets called with
//    next service in chain as parameter.
// 2. Middleware's call method gets called with normal request.
pub struct Auth;

// Middleware factory is `Transform` trait
// `S` - type of the next service
// `B` - type of response's body
impl<S, B> Transform<S, ServiceRequest> for Auth
where
    S: Service<ServiceRequest, Response = ServiceResponse<B>, Error = Error>,
    S::Future: 'static,
    B: 'static,
{
    type Response = ServiceResponse<B>;
    type Error = Error;
    type InitError = ();
    type Transform = SayHiMiddleware<S>;
    type Future = Ready<Result<Self::Transform, Self::InitError>>;

    fn new_transform(&self, service: S) -> Self::Future {
        ready(Ok(SayHiMiddleware { service }))
    }
}

pub struct SayHiMiddleware<S> {
    service: S,
}

impl<S, B> Service<ServiceRequest> for SayHiMiddleware<S>
where
    S: Service<ServiceRequest, Response = ServiceResponse<B>, Error = Error>,
    S::Future: 'static,
    B: 'static,
{
    type Response = ServiceResponse<B>;
    type Error = Error;
    type Future = LocalBoxFuture<'static, Result<Self::Response, Self::Error>>;
    forward_ready!(service);
    fn call(&self, req: ServiceRequest) -> Self::Future {
        // 获取请求头中的 token
        let token = match req.headers().get("token") {
            Some(value) => value.to_str().unwrap_or(""),
            None => "",
        };

        // 判断 token 是否有效
        if is_token_valid(token) {
            let fut = self.service.call(req);
            Box::pin(async move {
                let res = fut.await?;
                Ok(res)
            })
        } else {
            // token 无效，返回错误响应
            Box::pin(async move { Err(error::ErrorUnauthorized("Invalid token")) })
        }
    }
}

// 判断 token 是否有效的函数，你可以根据需要自定义实现
fn is_token_valid(token: &str) -> bool {
    println!("is_token_valid token: {}", token);
    let res = token::parse(token);
    match res {
        Ok(token) => {
            println!("token: {:#?}", token);
        }
        Err(e) => {
            println!("token parse error: {:#?}", e);
        }
    }
    // 在这里实现具体的 token 验证逻辑
    // 如果 token 有效，返回 true；否则返回 false
    // 例如，可以通过比较 token 和预设的有效 token 来判断
    token == "2222"
}
